package com.cps.frameauth.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cps.frameauth.model.dto.JwtBody;
import com.cps.frameauth.model.dto.UserInfoDTO;
import com.cps.frameauth.service.TokenService;
import com.cps.framecommon.exception.BusinessException;
import com.cps.frameredis.utils.RedisUtil;
import com.cps.frameauth.model.enums.TokenCodeEnum;
import com.cps.frameauth.service.OmTokenService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.security.NoSuchAlgorithmException;
import java.util.Objects;

/**
 * @author niuhui
 * @date 2021/12/2
 */
@Service
@Slf4j
public class OmTokenServiceImpl implements OmTokenService {
    @Resource
    private TokenService tokenService;
    @Resource
    private RedisUtil redisUtils;

    public static final String USER_TOKEN = "USER:OM:TOKEN:HOBBY:";

    @Override
    public UserInfoDTO checkOmToken(String token) {
        JwtBody body = null;
        try {
            body = tokenService.parseToken(token);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            throw new BusinessException(
                    TokenCodeEnum.AUTH_TOKEN_ILLEGAL.getCode(), TokenCodeEnum.AUTH_TOKEN_ILLEGAL.getMessage());
        }
        checkTokenExit(body, token);
        return JSON.parseObject(JSON.toJSON(body.getObject()).toString(), UserInfoDTO.class);
    }

    @Override
    public UserInfoDTO getUserByToken() {
        try {
            return checkToken();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            throw new BusinessException(
                    TokenCodeEnum.AUTH_TIME_OUT.getCode(), TokenCodeEnum.AUTH_TIME_OUT.getMessage());
        }
    }

    private UserInfoDTO checkToken() throws NoSuchAlgorithmException {
        ServletRequestAttributes requestAttributes =
                (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (Objects.isNull(requestAttributes)) {
            throw new BusinessException(
                    TokenCodeEnum.AUTH_TOKEN_EMPTY.getCode(), TokenCodeEnum.AUTH_TOKEN_EMPTY.getMessage());
        }
        HttpServletRequest request = requestAttributes.getRequest();
        String token = request.getHeader("token");
        if (StringUtils.isEmpty(token)) {
            throw new BusinessException(
                    TokenCodeEnum.AUTH_TOKEN_EMPTY.getCode(), TokenCodeEnum.AUTH_TOKEN_EMPTY.getMessage());
        }
        log.info("request url:{},method:{}", request.getRequestURL(), request.getMethod());
        JwtBody body = tokenService.parseToken(token);
        checkTokenExit(body, token);
        return JSON.parseObject(JSON.toJSON(body.getObject()).toString(), UserInfoDTO.class);
    }


    /**
     * 判断token是否合法
     *
     * @param body
     * @param token
     */
    private void checkTokenExit(JwtBody body, String token) {
        try {
            JSONObject user = JSONObject.parseObject(JSON.toJSON(body.getObject()).toString());
            Object userId = user.get("id");
            Object value = redisUtils.getRedis(USER_TOKEN + userId);
            if (!value.equals(token)) {
                throw new BusinessException(
                        TokenCodeEnum.AUTH_TOKEN_ILLEGAL.getCode(),
                        TokenCodeEnum.AUTH_TOKEN_ILLEGAL.getMessage());
            }
        } catch (Exception e) {
            throw new BusinessException(
                    TokenCodeEnum.AUTH_TOKEN_ILLEGAL.getCode(),
                    TokenCodeEnum.AUTH_TOKEN_ILLEGAL.getMessage());
        }
    }
}
